/**
 * 项目名：五位一体化工安全信息平台
 * 日期：    2019-11-25 13:04:58
 * Copyright (c) 2015- joysuch-版权所有
 */

package com.joysuch.wwyt.core.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.lang.UUID;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.google.common.base.Splitter;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.api.base.dto.*;
import com.joysuch.wwyt.api.basedata.service.BaseImageSyncService;
import com.joysuch.wwyt.baidu.enums.BaiduCodeEnum;
import com.joysuch.wwyt.baidu.req.BaiduFace;
import com.joysuch.wwyt.baidu.req.BaiduSample;
import com.joysuch.wwyt.baidu.util.DzPrtqUtils;
import com.joysuch.wwyt.bp.bean.BpCertificateListBean;
import com.joysuch.wwyt.bp.bean.BpDepartListBean;
import com.joysuch.wwyt.bp.entity.*;
import com.joysuch.wwyt.bp.entity.contractor.BpContractorStaff;
import com.joysuch.wwyt.bp.enums.DataStateTypes;
import com.joysuch.wwyt.bp.enums.WorkCertificateTypes;
import com.joysuch.wwyt.bp.repository.*;
import com.joysuch.wwyt.bp.service.BpCertificateService;
import com.joysuch.wwyt.bp.service.BpContractorStaffService;
import com.joysuch.wwyt.bp.service.BpDepartService;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.bean.*;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.security.CredentialsDigest;
import com.joysuch.wwyt.core.common.security.Digests;
import com.joysuch.wwyt.core.common.util.DateTimeUtil;
import com.joysuch.wwyt.core.common.util.Encodes;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.PageDataUtils.PageDataConvert;
import com.joysuch.wwyt.core.constant.Constants;
import com.joysuch.wwyt.core.entity.*;
import com.joysuch.wwyt.core.entity.dsl.QBaseCreditCardRecord;
import com.joysuch.wwyt.core.entity.dsl.QBaseLoginAccount;
import com.joysuch.wwyt.core.entity.dsl.QBaseUser;
import com.joysuch.wwyt.core.enums.*;
import com.joysuch.wwyt.core.mapper.BaseUserMapper;
import com.joysuch.wwyt.core.repository.*;
import com.joysuch.wwyt.core.security.ShiroUser;
import com.joysuch.wwyt.core.service.*;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.dzhapi.mapper.ApiBpContractorStaffMapper;
import com.joysuch.wwyt.edu.bean.EduCertUserDto;
import com.joysuch.wwyt.edu.bean.EduCertUserQueryBean;
import com.joysuch.wwyt.edu.entity.EduCertificateUser;
import com.joysuch.wwyt.edu.entity.EduExamRecord;
import com.joysuch.wwyt.edu.repository.EduCertificateUserDao;
import com.joysuch.wwyt.edu.repository.EduExamRecordDao;
import com.joysuch.wwyt.monitoringcenter.service.LocateServerService;
import com.joysuch.wwyt.util.*;
import com.querydsl.core.types.ExpressionUtils;
import com.querydsl.core.types.Predicate;
import com.querydsl.core.types.dsl.BooleanExpression;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.Assert;
import org.json.JSONObject;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Transactional(rollbackFor = Exception.class)
@Slf4j
public class BaseUserServiceImpl implements BaseUserService {
    @Autowired
    private BaseUserDao dao;
    @Autowired
    private BpDepartDao departDao;
    @Autowired
    private BpJobDao jobDao;
    @Autowired
    private BaseLoginAccountDao baseLoginAccountDao;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;
    @Autowired
    private BaseImageRespositoryDao baseImageRespositoryDao;
    @Autowired
    private BpWorkTypeDao bpWorkTypeDao;
    @Autowired
    private BpCertificateDao certificateDao;
    @Autowired
    private BaseLoginAccountService baseLoginAccountService;
    @Autowired
    private BpCertificateService certificateService;
    @Autowired
    private EduExamRecordDao eduExamRecordDao;
    @Autowired
    private BaseTypeGroupItemDao typeGroupItemDao;
    @Autowired
    private BpEnterpriseInfoDao bpEnterpriseInfoDao;
    @Autowired
    private MailService mailService;
    @Autowired
    private RedisClient redisClient;
    private static final int SALT_SIZE = 8;
    @Autowired
    private CredentialsDigest credentialsDigest;
    @Autowired
    private BpContractorStaffService bpContractorStaffService;
    @Autowired
    private LocateServerService locateServerService;
    @Autowired
    private BaseConfigService baseConfigService;
    @Autowired
    private BaseCreditCardRecordDao baseCreditCardRecordDao;
    @Autowired
    private BaseTypeGroupItemDao baseTypeGroupItemDao;
    @Autowired
    private BaseTypeGroupDao typeGroupDao;
    @Autowired
    private BpContractorStaffDao bpContractorStaffDao;
    @Autowired
    private EduCertificateUserDao eduCertificateUserDao;
    @Autowired
    private ZipProcessService zipProcessService;
    @Autowired
    private BaseImageSyncService baseImageSyncService;
    @Autowired
    private BaseUserMapper baseUserMapper;
    @Value("${wwyt.base.serverUrl}")
    private String serverUrl;
    // 强制同步工号作为登录账号
    @Value("${wwyt.biz.user.account.forceSyncCodeAsLoginAccount}")
    private boolean forceSyncCodeAsLoginAccount;
    // 默认密码
    @Value("${wwyt.biz.user.account.defaultPassword}")
    private String defaultPassword;

    @Autowired
    private BaseRoleDao baseRoleDao;

    @Autowired
    private BaseRoleUserLoginRoleDao baseRoleUserLoginRoleDao;
    @Autowired
    private BpDepartService departService;

    @Autowired
    private BaseImageRepositoryService baseImageRepositoryService;

    @Autowired
    private BaseUserFaceLogService baseUserFaceLogService;

    @Autowired
    private ApiBpContractorStaffMapper contractorStaffMapper;


    @Value("${wwyt.image.upload.dir}")
    private String imageUploadDir;

    @Override
    public ResultBean add(BpUserListBean u) throws Exception {
        String regex = "[0-9a-zA-Z_-]{1,64}";
        if (StringUtils.isNotBlank(u.getImei()) && !u.getImei().matches(regex)) {
            return ResultBean.wrapErrorResultDefault(String.format("IMEI[%s]格式不正确,IMEI为64位内大小写字母或数字或-或_组成", u.getImei()));
        }
        if (u.getCode() != null && dao.countOfCode(u.getCode()) > 0) {
            return ResultBean.wrapErrorResultDefault(String.format("工号[%s]已存在", u.getCode()));
        }
        if (u.getCode() != null && dao.countOfRealName(u.getRealName()) > 0) {
            return ResultBean.wrapErrorResultDefault(Status.USER_NAME_EXIST.getMsg());
        }
        BaseUser b = new BaseUser();
        b.setAddress(u.getAddress());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (!org.springframework.util.StringUtils.isEmpty(u.getBirthday())) {
            b.setBirthday(sdf.parse(u.getBirthday()));
        }
        DateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
        try {
            if (u.getJoinWorkDate() != null && StringUtils.isNotBlank(u.getJoinWorkDate())) {
                b.setJoinWorkDate(fmt.parse(u.getJoinWorkDate()));
            }
            if (u.getEnterDate() != null && StringUtils.isNotBlank(u.getEnterDate())) {
                b.setEnterDate(fmt.parse(u.getEnterDate()));
            }
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        BeanUtils.copyProperties(u, b);
        if (u.getImage() != null) {
            b.setIdCardImgId(u.getImage().getId());
        }
        if (u.getCap() != null) {
            b.setCapId(u.getCap().getId());
        }
        b.setLocateSync(false);
        if (u.getCode() == null) {
            b.setCode(bizCodeGeneratorFacade.renYuan());
        } else {
            b.setCode(u.getCode());
        }
        // 新增添加uniqueId
        b.setUniqueId(SnowFlakeUtil.getUserId());
        BaseUser save = dao.save(b);
        if (b.getIdCardImgId() != null) {
            String faceToken = addUserFace(b.getIdCardImgId(), b.getTenentId(), b.getOrgCode(), b.getId());
            if (StringUtils.isNotBlank(faceToken) && !faceToken.equals(b.getFaceToken())) {
                b.setFaceToken(faceToken);
            }
        }
        // 判断 定位卡 门禁卡号是否重复
        this.checkUser(save.getCardNumber(), save.getSn(), "user");
        updateJobUserCount(u.getJob());
        String[] certificateId = u.getCertificateIds();
        if (certificateId != null) {
            for (String s : certificateId) {
                BpCertificate one = certificateDao.getOne(new Long(s));
                one.setUsetId(save.getId());
                certificateDao.save(one);
            }
        }

        if (forceSyncCodeAsLoginAccount) {
            addOrUpdateLoginAccount(save);
        }
        // 新增用户添加默认角色： 员工
        addDefaultRole4User(save.getId());
        // 同步人员
        if (isEmployeeSyncOpen()) {
            locateServerService.syncLocateUsers(Lists.newArrayList(save), 0);
        }
        return ResultBean.defaultSuccessResult();
    }

    /**
     * 判断 定位卡 门禁卡号是否重复
     *
     * @param cardNumber
     * @param sn
     */
    @Override
    public void checkUser(String cardNumber, String sn, String flag) {
        List<BpContractorStaff> staffCards = new ArrayList<>();
        List<BaseUser> userCards = new ArrayList<>();
        List<BpContractorStaff> staffSn = new ArrayList<>();
        List<BaseUser> userSn = new ArrayList<>();
        if (StringUtils.isNotBlank(cardNumber)) {
            staffCards = bpContractorStaffDao.findByCardNumberAndState(cardNumber, 1);
            userCards = dao.findByCardNumber(cardNumber);
        }
        if (StringUtils.isNotBlank(sn)) {
            if (!Validators.validateMac(sn)) {
                throw new IllegalArgumentException("定位卡号必须12位数字或a(A)-f(F)字母组合");
            }
            staffSn = bpContractorStaffDao.findBySnAndState(sn, 1);
            userSn = dao.findBySn(sn);
        }
        if (StringUtils.isNotBlank(flag) && flag.equals("user")) {
            if (!CollectionUtils.isEmpty(staffCards) && staffCards.size() > 0) {
                throw new IllegalArgumentException("门禁卡号已被承包商人员使用");
            }
            if (!CollectionUtils.isEmpty(userCards) && userCards.size() > 1) {
                throw new IllegalArgumentException("门禁卡号已被人员使用");
            }
            if (!CollectionUtils.isEmpty(staffSn) && staffSn.size() > 0) {
                throw new IllegalArgumentException("定位卡号已被承包商人员使用");
            }
            if (!CollectionUtils.isEmpty(userSn) && userSn.size() > 1) {
                throw new IllegalArgumentException("定位卡号已被人员使用");
            }
        } else if (StringUtils.isNotBlank(flag) && flag.equals("staff")) {
            if (!CollectionUtils.isEmpty(staffCards) && staffCards.size() > 1) {
                throw new IllegalArgumentException("门禁卡号已被承包商人员使用");
            }
            if (!CollectionUtils.isEmpty(userCards) && userCards.size() > 0) {
                throw new IllegalArgumentException("门禁卡号已被人员使用");
            }
            if (!CollectionUtils.isEmpty(staffSn) && staffSn.size() > 1) {
                throw new IllegalArgumentException("定位卡号已被承包商人员使用");
            }
            if (!CollectionUtils.isEmpty(userSn) && userSn.size() > 0) {
                throw new IllegalArgumentException("定位卡号已被人员使用");
            }
        }
    }

    private boolean isEmployeeSyncOpen() {
        BaseConfig config = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_SERVER_EMPLOYEE_SYNC_OPEN);
        return config == null ? false : "true".equalsIgnoreCase(config.getValue());
    }

    // 每个新增用户添加默认角色： 员工
    private void addDefaultRole4User(Long userId) {
        BaseRole baseRole = baseRoleDao.findFirstByName(Constants.USER_DEFAULT_ROLE_NAME);
        if (baseRole != null) {
            BaseRoleUserLoginRole userRole = new BaseRoleUserLoginRole();
            userRole.setUserId(userId);
            userRole.setRoleId(baseRole.getId());
            baseRoleUserLoginRoleDao.save(userRole);
        }

    }

    @Override
    public ResultBean update(BpUserListBean u) throws Exception {
        String regex = "[0-9a-zA-Z_-]{1,64}";
        if (StringUtils.isNotBlank(u.getImei()) && !u.getImei().matches(regex)) {
            return ResultBean.wrapErrorResultDefault(String.format("IMEI[%s]格式不正确,IMEI为64位内大小写字母或数字或-或_组成", u.getImei()));
        }
        if (u.getCode() != null && dao.countOfCodeExcludeId(u.getCode(), u.getId()) > 0) {
            return ResultBean.wrapErrorResultDefault(String.format("工号[%s]已存在", u.getCode()));
        }
        if (u.getCode() != null && dao.countOfRealNameAndIdNotEq(u.getRealName(), u.getId()) > 0) {
            return ResultBean.wrapErrorResultDefault(Status.USER_NAME_EXIST.getMsg());
        }
        BaseUser b = dao.findById(u.getId()).get();
        if (u.getImage() != null && u.getImage().getId() != null) {
            String faceToken = "";
            if (b.getIdCardImgId() == null) {
                faceToken = addUserFace(u.getImage().getId(), b.getTenentId(), b.getOrgCode(), b.getId());
            } else {
                faceToken = updateUserFace(b.getIdCardImgId(), u.getImage().getId(), b.getTenentId(), b.getOrgCode(), b.getId());
            }
            if (StringUtils.isNotBlank(faceToken) && !faceToken.equals(b.getFaceToken())) {
                b.setFaceToken(faceToken);
            }
        } else {
            //如果修改去掉头像，删除人员
            String groupId = getGroupId();
            if (StringUtils.isNotBlank(b.getFaceToken())) {
                try {
                    JSONObject jsonObject = new BaiduFace().faceDelete(BaiduSample.client, u.getId().toString(), groupId, b.getFaceToken(), null);
                    String errorCode = jsonObject.get("error_code").toString();
                    if (errorCode.equals("0")) {
                        b.setFaceToken("");
                    }
                } catch (Exception e) {
                    log.error("删除百度token报错");
                }
            }
        }
        Long oldJobId = b.getJob();
        Long newJobId = u.getJob();
        boolean codeChanged = !Objects.equals(u.getCode(), b.getCode());
        BeanUtils.copyProperties(u, b);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String birthday = u.getBirthday();
        String enterDate = u.getEnterDate();
        b.setBirthday(org.springframework.util.StringUtils.isEmpty(birthday) ? null : sdf.parse(birthday));
        b.setEnterDate(org.springframework.util.StringUtils.isEmpty(enterDate) ? null : sdf.parse(enterDate));
        if (u.getImage() != null) {
            b.setIdCardImgId(u.getImage().getId());
        }
        if (u.getCap() != null) {
            b.setCapId(u.getCap().getId());
        }
        if (u.getJoinWorkDate() != null && !u.getJoinWorkDate().isEmpty()) {
            b.setJoinWorkDate(sdf.parse(u.getJoinWorkDate()));
        } else {
            b.setJoinWorkDate(null);
        }
        // 修改时确保有uniqueId
        if (b.getUniqueId() == null) {
            b.setUniqueId(SnowFlakeUtil.getUserId());
        }
        BaseUser save = dao.save(b);
        // 判断 定位卡 门禁卡号是否重复
        checkUser(save.getCardNumber(), save.getSn(), "user");
        if (!Objects.equals(oldJobId, newJobId)) {
            updateJobUserCount(oldJobId);
            updateJobUserCount(newJobId);
        }
        // 账号变化或者没有账号
        if (forceSyncCodeAsLoginAccount && (codeChanged || baseLoginAccountDao.findByBaseUser(save) == null)) {
            addOrUpdateLoginAccount(save);
        }
        String locateVersion = locateServerService.getLocateVersion();
        // 同步人员
        if (isEmployeeSyncOpen()) {
            if ("3.x".equals(locateVersion)) {
                locateServerService.syncLocateUsers(Lists.newArrayList(save), 0);
            } else {
                locateServerService.syncLocateUsers(Lists.newArrayList(save), 0);
            }
        }
        return ResultBean.defaultSuccessResult();
    }

    private void addOrUpdateLoginAccount(BaseUser save) {
        baseLoginAccountService.addOrUpdateLoginAccount(save, save.getCode(), defaultPassword);
    }

    /**
     * 人脸更新
     *
     * @param oldImageId
     * @param newImageId
     * @param tenentId
     * @param orgCode
     * @param userId
     * @return
     */
    public String updateUserFace(Long oldImageId, Long newImageId, Long tenentId, String orgCode, Long userId) {
        BaseConfig syncConfig = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_SYNC);
        if (syncConfig == null || StringUtils.isBlank(syncConfig.getValue()) || syncConfig.getValue().equals("关闭")) {
            return "";
        }
        BaseConfig baiduFaceAppID = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_ID);
        if (baiduFaceAppID == null || StringUtils.isBlank(baiduFaceAppID.getValue())) {
            return "";
        }
        BaseConfig baiduFaceAppKey = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_KEY);
        if (baiduFaceAppKey == null || StringUtils.isBlank(baiduFaceAppKey.getValue())) {
            return "";
        }
        BaseConfig baiduFaceAppSecret = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_SECRET);
        if (baiduFaceAppSecret == null || StringUtils.isBlank(baiduFaceAppSecret.getValue())) {
            return "";
        }
        String faceToken = "";
        if (oldImageId == null || !oldImageId.equals(newImageId)) {
            BaseUserFaceLog log = new BaseUserFaceLog();
            log.setSyncTime(new Date());
            log.setUserId(userId);
            try {
                String path = baseImageRepositoryService.findAbsolutePathById(newImageId);
                String imageBase64 = DzPrtqUtils.readFileToBase64(new FileInputStream(path));
                String groupId = getGroupId();
                JSONObject jsonObject = new BaiduFace().updateUser(BaiduSample.client, imageBase64, "BASE64", groupId, userId.toString(), null);
                String errorCode = jsonObject.get("error_code").toString();
                if (errorCode.equals("0")) {
                    JSONObject result = jsonObject.getJSONObject("result");
                    faceToken = result.getString("face_token");
                } else {
                    BaiduCodeEnum baiduCodeEnum = BaiduCodeEnum.find(errorCode);
                    log.setErrMsg(baiduCodeEnum == null ? "" : baiduCodeEnum.getErrMsg());
                }
                log.setErrCode(errorCode);
                log.setDetail(jsonObject.toString());
                baseUserFaceLogService.save(log);
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        return faceToken;
    }

    /**
     * 人脸注册
     *
     * @param newImageId
     * @param tenentId
     * @param orgCode
     * @param userId
     * @return
     */
    public String addUserFace(Long newImageId, Long tenentId, String orgCode, Long userId) {
        BaseConfig syncConfig = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_SYNC);
        if (syncConfig == null || StringUtils.isBlank(syncConfig.getValue()) || syncConfig.getValue().equals("关闭")) {
            return "";
        }
        BaseConfig baiduFaceAppID = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_ID);
        if (baiduFaceAppID == null || StringUtils.isBlank(baiduFaceAppID.getValue())) {
            return "";
        }
        BaseConfig baiduFaceAppKey = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_KEY);
        if (baiduFaceAppKey == null || StringUtils.isBlank(baiduFaceAppKey.getValue())) {
            return "";
        }
        BaseConfig baiduFaceAppSecret = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_SECRET);
        if (baiduFaceAppSecret == null || StringUtils.isBlank(baiduFaceAppSecret.getValue())) {
            return "";
        }
        String faceToken = "";
        BaseUserFaceLog log = new BaseUserFaceLog();
        log.setSyncTime(new Date());
        log.setUserId(userId);
        try {
            String path = baseImageRepositoryService.findAbsolutePathById(newImageId);
            String imageBase64 = DzPrtqUtils.readFileToBase64(new FileInputStream(path));
//                orgCode=orgCode.replaceAll("-","_");
//                String groupId=tenentId+"_"+orgCode;
            String groupId = getGroupId();
            JSONObject jsonObject = new BaiduFace().addUser(BaiduSample.client, imageBase64, "BASE64", groupId, userId.toString(), null);
            String errorCode = jsonObject.get("error_code").toString();
            if (errorCode.equals("0")) {
                JSONObject result = jsonObject.getJSONObject("result");
                faceToken = result.getString("face_token");
            } else {
                BaiduCodeEnum baiduCodeEnum = BaiduCodeEnum.find(errorCode);
                log.setErrMsg(baiduCodeEnum == null ? "" : baiduCodeEnum.getErrMsg());
            }
            log.setErrCode(errorCode);
            log.setDetail(jsonObject.toString());
            baseUserFaceLogService.save(log);
        } catch (IOException e) {
            e.printStackTrace();
        }
        return faceToken;
    }

    /**
     * @param jobId
     */
    protected void updateJobUserCount(Long jobId) {
        BpJob job = jobDao.getOne(jobId);
        List<BaseUser> userList = dao.findByJob(jobId);
        job.setStaffCount(CollectionUtils.isEmpty(userList) ? 0 : userList.size());
        jobDao.save(job);
    }

    @Override
    public Page<BaseUserFindAllBean> findByPage(Pageable page, BpUserSearchBean bpUserSearchBean, Long chiefId) {
        QBaseUser baseUser = QBaseUser.baseUser;
        Predicate predicate = baseUser.isNotNull();
        predicate = bpUserSearchBean.getName() == null ? predicate
                : ExpressionUtils.and(predicate,
                ExpressionUtils.or(baseUser.realName.like("%" + bpUserSearchBean.getName() + "%"),
                        baseUser.code.like("%" + bpUserSearchBean.getName() + "%")));
        predicate = bpUserSearchBean.getSn() == null ? predicate
                : ExpressionUtils.and(predicate, baseUser.sn.like("%" + bpUserSearchBean.getSn() + "%"));
        predicate = bpUserSearchBean.getJob() == null ? predicate
                : ExpressionUtils.and(predicate, baseUser.job.eq(bpUserSearchBean.getJob()));
        predicate = bpUserSearchBean.getDepartId() == null ? predicate
                : ExpressionUtils.and(predicate, baseUser.departId.eq(bpUserSearchBean.getDepartId()));
        if (bpUserSearchBean.getPersonTypeId() != null) {
            predicate = ExpressionUtils.and(predicate, baseUser.personTypeId.eq(bpUserSearchBean.getPersonTypeId()));
        }
        if (chiefId != null) {
            List<Long> subDepartsIds = findDepartAndSubDepartIds(chiefId);
            predicate = ExpressionUtils.and(predicate, baseUser.departId.in(subDepartsIds));
        }
        if (bpUserSearchBean.getLocateSync() != null) {
            predicate = ExpressionUtils.and(predicate, baseUser.locateSync.eq(bpUserSearchBean.getLocateSync()));
        }
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(baseUser.state.notIn(DataStateTypes.DELETE.getState()), baseUser.state.isNull()));

        ArrayList<BaseUserFindAllBean> list = new ArrayList<>();
        page = PageDataUtils.addOrderByDesc(page, "id");
        Page<BaseUser> all = dao.findAll(predicate, page);
        for (BaseUser u : all) {
            BaseUserFindAllBean b = new BaseUserFindAllBean();
            b.setAccount(username(u.getId()));
            b.setId(u.getId());
            b.setCode(u.getCode());
            b.setName(u.getRealName());
            b.setDepartId(u.getDepartId());
            b.setLocateSync(u.isLocateSync());
            b.setSn(u.getSn());
            if (u.getDepartId() != null) {
                // 部门
                b.setDepartName(departDao.getNameById(u.getDepartId()));
            }
            b.setJob(u.getJob());
            if (u.getJob() != null) {
                b.setJobName(jobDao.getNameById(u.getJob()));
            }
            b.setRole(u.getRole());
            if (u.getRole() != null) {
                b.setRoleName(UserRoleTypes.getRoleNameByIndex(u.getRole().intValue()));
            }
            // 账号开启/关闭状态
            if (baseLoginAccountDao.findByBaseUser(u) != null) {
                // b.setLoginShowState(baseLoginAccountDao.findByUserDetailId(u.getId()).getShowState());
                b.setLoginShowState(baseLoginAccountDao.findByBaseUser(u).getShowState());
            }
            if (u.getPersonTypeId() != null) {
                b.setPersonTypeName(typeGroupItemDao.findNameById(u.getPersonTypeId()));
            }

            b.setAlarmTemplateId(u.getAlarmTemplateId());
            b.setAlarmTemplateName(u.getAlarmTemplateName());
            b.setFaceToken(u.getFaceToken());
            b.setIdCardImgId(u.getIdCardImgId());
            list.add(b);
        }
        PageImpl<BaseUserFindAllBean> baseUserFindAllBeans = new PageImpl<>(list, page, all.getTotalElements());
        return baseUserFindAllBeans;
    }


    @Override
    public Page<BaseUserFindAllBean> findByPage(Pageable page, BpUserSearchBean bpUserSearchBean, Long chiefId, String sort, String... sortField) {
        log.info("开始1++++++++++" + System.currentTimeMillis());
        QBaseUser baseUser = QBaseUser.baseUser;
        Predicate predicate = baseUser.isNotNull();

        predicate = bpUserSearchBean.getName() == null ? predicate
                : ExpressionUtils.and(predicate, baseUser.realName.like("%" + bpUserSearchBean.getName() + "%"));

        predicate = bpUserSearchBean.getCode() == null ? predicate
                : ExpressionUtils.and(predicate, baseUser.code.eq(bpUserSearchBean.getCode()));

        predicate = bpUserSearchBean.getDepartId() == null ? predicate
                : ExpressionUtils.and(predicate, baseUser.departId.eq(bpUserSearchBean.getDepartId()));
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(baseUser.state.notIn(DataStateTypes.DELETE.getState()), baseUser.state.isNull()));

        ArrayList<BaseUserFindAllBean> list = new ArrayList<>();
        page = PageDataUtils.addOrderSort(page, sort, sortField);
        log.info("开始2++++++++++" + System.currentTimeMillis());
        Page<BaseUser> all = dao.findAll(predicate, page);
        long total = 0;
        if (CollectionUtil.isNotEmpty(all)) {
            for (BaseUser u : all) {
                BaseUserFindAllBean b = new BaseUserFindAllBean();
                b.setAccount(username(u.getId()));
                b.setId(u.getId());
                b.setCode(u.getCode());
                b.setName(u.getRealName());
                b.setDepartId(u.getDepartId());
                b.setLocateSync(u.isLocateSync());
                b.setSn(u.getSn());
//            if (u.getDepartId() != null) {
//                // 部门
//                b.setDepartName(departDao.getNameById(u.getDepartId()));
//            }
                b.setAlarmTemplateId(u.getAlarmTemplateId());
                b.setAlarmTemplateName(u.getAlarmTemplateName());
                list.add(b);
            }
            total = all.getTotalElements();
        }
        log.info("开始3++++++++++" + System.currentTimeMillis());
        PageImpl<BaseUserFindAllBean> baseUserFindAllBeans = new PageImpl<>(list, page, total);
        log.info("开始4++++++++++" + System.currentTimeMillis());
        return baseUserFindAllBeans;
    }

    @Override
    public String username(Long id) {
        QBaseLoginAccount baseLoginAccount = QBaseLoginAccount.baseLoginAccount;
        Predicate predicate1 = baseLoginAccount.isNotNull();
        predicate1 = id == null ? predicate1 : ExpressionUtils.and(predicate1, baseLoginAccount.baseUser.id.eq(id));
        Iterable<BaseLoginAccount> als = baseLoginAccountDao.findAll(predicate1);

        if (als != null) {
            for (BaseLoginAccount al : als) {
                return "已有账户";
            }
        }
        return "未有账户";
    }

    @Override
    public List<Long> findDepartAndSubDepartIds(Long chiefId) {
        BpDepart one = departDao.getOne(chiefId);
        List<Long> ids = departDao.findSubDepartIdsByCode(one.getCode());
        ids.add(0, chiefId);
        return ids;
    }

    @Override
    public void delete(Long id) {
        if (Context.getCurrentUserId() != null && Context.getCurrentUserId().equals(id)) {
            throw new IllegalArgumentException("请勿删除自己的账号");
        }
        BaseUser one = dao.getOne(id);
        one.setState(DataStateTypes.DELETE.getState());
        // baseLoginAccountDao.deleteByBaseUser(one);
        baseLoginAccountDao.deleteByUserId(one.getId());
        BaseUser save = dao.save(one);
        if (one.getJob() != null) {
            updateJobUserCount(one.getJob());
        }
        // 证书模块：执证人员被删除，相应执证记录也应删除
        // 文君:删除人员 不删除持证记录
        // eduCertificateUserDao.deleteByUserIdAndUserContractorFlag(id, 0);

        // 同步人员
        if (isEmployeeSyncOpen()) {
            locateServerService.syncLocateUsers(Lists.newArrayList(save), 0);
        }
        //删除百度人脸
        if (StringUtils.isNotBlank(one.getFaceToken())) {
//            String orgCode=one.getOrgCode().replaceAll("-","_");
//            String groupId=one.getTenentId()+"_"+orgCode;
            String groupId = getGroupId();
            try {
                JSONObject jsonObject = new BaiduFace().faceDelete(BaiduSample.client, id.toString(), groupId, one.getFaceToken(), null);
            } catch (Exception e) {
                log.error("删除百度token报错");
            }
        }

    }

    @Override
    public BpUserBean selectByUserId(Long id) {
        BpUserBean bean = new BpUserBean();
        BaseUser u = dao.findById(id).get();
        bean.setDepartName(u.getDepartId());
        bean.setJobId(u.getJob());
        bean.setDepartId(u.getDepartId());
        bean.setRealName(u.getRealName());
        bean.setUserDepartName(departDao.findDepartNameById(u.getDepartId()));
        bean.setUserJobName(jobDao.findNameById(u.getJob()));
        return bean;
    }

    @Override
    public BpUserListBean findById(Long id) {
        BaseUser u = dao.findById(id).get();
        BpUserListBean b = new BpUserListBean();
        b.setAddress(u.getAddress());
        if (u.getWorkCompanyId() != null) {
            BpEnterpriseInfo bpEnterpriseInfo = bpEnterpriseInfoDao.findById(u.getWorkCompanyId()).orElse(null);
            b.setWorkCompanyName(bpEnterpriseInfo != null ? bpEnterpriseInfo.getName() : "");
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        if (u.getBirthday() != null) {
            b.setBirthday(sdf.format(u.getBirthday()));
        }
        if (u.getEnterDate() != null) {
            b.setEnterDate(sdf.format(u.getEnterDate()));
        }
        BeanUtils.copyProperties(u, b);
        if (u.getDepartId() != null) {
            // 部门
            departDao.findById(u.getDepartId()).ifPresent(one -> b.setDepartName(one.getName()));
        }
        b.setEducation(u.getEducation());
        if (u.getEducation() != null) {
            // 学历
            typeGroupItemDao.findById(u.getEducation()).ifPresent(one -> b.setEducationName(one.getName()));
        }

        if (u.getHealthStatus() != null) {
            // 健康
            typeGroupItemDao.findById(u.getHealthStatus()).ifPresent(one -> b.setHealthStatusName(one.getName()));
        }

        BaseAttachmentBean baseAttachmentBean = new BaseAttachmentBean();
        baseAttachmentBean.setId(u.getIdCardImgId());
        if (StringUtils.isNotEmpty(u.getFacePic())) {
            baseAttachmentBean.setDownloadUrl(u.getFacePic());
        } else {
            baseAttachmentBean.setDownloadUrl(serverUrl + "/image/view?id=" + u.getIdCardImgId());
        }
        b.setImage(baseAttachmentBean);
        BaseAttachmentBean cap = new BaseAttachmentBean();
        cap.setId(u.getCapId());
        cap.setDownloadUrl(serverUrl + "/image/view?id=" + u.getCapId());
        b.setCap(cap);
        if (u.getIdCardType() != null) {
            b.setIdCardName(BaseIdCardTypes.getIdName(u.getIdCardType().intValue()));
        }
        if (u.getJoinWorkDate() != null) {
            b.setJoinWorkDate(sdf.format(u.getJoinWorkDate()));
        }

        if (u.getJob() != null) {
            BpJob one = jobDao.getOne(u.getJob());
            b.setJobName(one.getName());
        }
        if (u.getNation() != null) {
            // 民族
            typeGroupItemDao.findById(u.getNation()).ifPresent(one -> b.setNationName(one.getName()));
        }
        if (u.getWorkTypeId() != null) {
            bpWorkTypeDao.findById(u.getWorkTypeId()).ifPresent(one -> b.setWorkTypeName(one.getName()));
        }
        if (u.getRole() != null) {
            if (u.getRole() == 0) {
                // 身份
                b.setRoleName("员工");
            }
            if (u.getRole() == 1) {
                // 身份
                b.setRoleName("管理人员");
            }
            if (u.getRole() == 2) {
                // 身份
                b.setRoleName("企业负责人");
            }
        }
        if (b.getId() != null) {
            List<BpCertificateListBean> page = certificateService.getPage(b.getId());
            if (page != null) {
                b.setCertificateListBeans(page);
            }
        }
        if (u.getPersonTypeId() != null) {
            b.setPersonTypeName(typeGroupItemDao.getNameById(u.getPersonTypeId()));
        }
        b.setPoliticallyId(u.getPoliticallyId());
        if (u.getPoliticallyId() != null) {
            b.setPoliticallyName(typeGroupItemDao.getNameById(u.getPoliticallyId()));
        }
        if (StringUtils.isNotBlank(u.getAutograph())) {
            b.setAutograph(u.getAutograph());
//            int i = u.getAutograph().indexOf("=");
//            Long imageId = Long.parseLong(u.getAutograph().substring(i+1));
//            String path = baseImageRepositoryService.findById(imageId).getOriginPath();
            b.setPath(u.getFlowSignature());
        }
        return b;
    }

    @Override
    public List<SimpleUserBean> findUserSimpleList(Integer userContractorFlag) {
        userContractorFlag = userContractorFlag == null ? 0 : userContractorFlag;
        if (userContractorFlag == 0) {
            return baseUserMapper.findAllUser();
        } else {
            return bpContractorStaffService.getAllContractorSimpleList();
        }
    }

    @Override
    public Page<BaseUserListBean> findDetailInfoByPage(Pageable page, BaseUserListSearchBean condition) {
        page = PageDataUtils.addOrderByDesc(page, "id");
        Integer userContractorFlag = condition.getUserContractorFlag();
        userContractorFlag = userContractorFlag == null ? 0 : userContractorFlag;
        if (userContractorFlag == 0) {
            List<BpEnterpriseInfo> infoList = bpEnterpriseInfoDao.findAll();
            Map<Long, BpEnterpriseInfo> infoMap = infoList.stream().collect(Collectors.toMap(BpEnterpriseInfo::getId,
                    Function.identity()));
            QBaseUser point = QBaseUser.baseUser;
            Predicate predicate = null;
            if (condition.getNameOrCode() != null) {
                predicate = point.realName.like("%" + condition.getNameOrCode() + "%");
                predicate = ExpressionUtils.or(predicate, point.code.like("%" + condition.getNameOrCode() + "%"));
            }
            if (condition.getDepartId() != null) {
                BooleanExpression eq = point.departId.eq(condition.getDepartId());
                predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
            }
            if (condition.getJobId() != null) {
                BooleanExpression eq = point.job.eq(condition.getJobId());
                predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
            }
            if (condition.getCompanyId() != null) {
                BooleanExpression eq = point.workCompanyId.eq(condition.getCompanyId());
                predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
            }
            predicate = ExpressionUtils.and(predicate,
                    ExpressionUtils.or(point.state.notIn(DataStateTypes.DELETE.getState()), point.state.isNull()));

            Page<BaseUser> all = predicate == null ? dao.findAll(page) : dao.findAll(predicate, page);

            List<BaseUser> contents = all.getContent();
            List<Long> departIds = contents.stream().map(BaseUser::getDepartId).collect(Collectors.toList());
            List<Long> jobs = contents.stream().map(BaseUser::getJob).collect(Collectors.toList());
            List<Long> ids = contents.stream().map(BaseUser::getId).collect(Collectors.toList());
            if (!CollectionUtils.isEmpty(jobs)){
            List<BpDepart> departs = departDao.findByIds(departIds);
            Map<Long, String> departNameMap = departs.stream().collect(Collectors.toMap(BpDepart::getId, BpDepart::getName));
            List<BpJob> bpJobs = jobDao.findbyIds(jobs);
            Map<Long, String> jobMap = bpJobs.stream().collect(Collectors.toMap(BpJob::getId, BpJob::getName));
            List<BpCertificate> certs = certificateService.findCertNameByUserIdsAndType(ids, WorkCertificateTypes.TE_ZHONG_ZUO_YE.getCode());
            Map<Long, String> certMap = certs.stream().collect(Collectors.toMap(BpCertificate::getUsetId, BpCertificate::getName));

            return PageDataUtils.convertPageData(all, f -> {
                BaseUserListBean bean = new BaseUserListBean();
                bean.setId(f.getId());
                bean.setPhoneNumber(f.getTelephone());
                bean.setName(f.getRealName());
                bean.setCode(f.getCode());
                bean.setDepartId(f.getDepartId());
                BpEnterpriseInfo enterpriseInfo = infoMap.get(f.getWorkCompanyId());
                bean.setCompanyId(enterpriseInfo == null ? null : enterpriseInfo.getId());
                bean.setCompanyName(enterpriseInfo == null ? null : enterpriseInfo.getName());
                bean.setUserContractorFlag(0);
                if (f.getDepartId() != null) {
                    bean.setDepartName(departNameMap.get(f.getDepartId()));
                }
                bean.setJobId(f.getJob());
                if (f.getJob() != null) {
                    bean.setJobName(jobMap.get(f.getJob()));
                }
                bean.setCertName(certMap.get(f.getId()));
                bean.setGender(f.getGender());
                return bean;
            });
            }
            return  bpContractorStaffService.userModelPage(condition.getNameOrCode(), condition.getCompanyId(), page);
        } else {
            return bpContractorStaffService.userModelPage(condition.getNameOrCode(), condition.getCompanyId(), page);
        }
    }

    @Override
    public Page<BaseUserListBean> findDetailInfoByPageWf(Pageable page, BaseUserListWfSearchBean condition) {
        page = PageDataUtils.addOrderByDesc(page, "id");
        Integer userContractorFlag = condition.getUserContractorFlag();
        userContractorFlag = userContractorFlag == null ? 0 : userContractorFlag;
        if (userContractorFlag == 0) {
            List<BpEnterpriseInfo> infoList = bpEnterpriseInfoDao.findAll();
            Map<Long, BpEnterpriseInfo> infoMap = infoList.stream().collect(Collectors.toMap(BpEnterpriseInfo::getId,
                    Function.identity()));
            QBaseUser point = QBaseUser.baseUser;
            Predicate predicate = null;
            if (condition.getNameOrCode() != null) {
                predicate = point.realName.like("%" + condition.getNameOrCode() + "%");
                predicate = ExpressionUtils.or(predicate, point.code.like("%" + condition.getNameOrCode() + "%"));
            }
            if (condition.getDepartId() != null) {
                BooleanExpression eq = point.departId.eq(condition.getDepartId());
                predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
            }
            if (condition.getJobId() != null) {
                BooleanExpression eq = point.job.eq(condition.getJobId());
                predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
            }
            if (condition.getCompanyId() != null) {
                BooleanExpression eq = point.workCompanyId.eq(condition.getCompanyId());
                predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
            }
            if (condition.getTenantId() != null) {
                BooleanExpression eq = point.tenentId.eq(condition.getTenantId());
                predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
            }
            if (condition.getOrgCode() != null) {
                BooleanExpression eq = point.orgCode.like(condition.getOrgCode() + "%");
                predicate = predicate == null ? eq : ExpressionUtils.and(predicate, eq);
            }
            predicate = ExpressionUtils.and(predicate,
                    ExpressionUtils.or(point.state.notIn(DataStateTypes.DELETE.getState()), point.state.isNull()));

            Page<BaseUser> all = predicate == null ? dao.findAll(page) : dao.findAll(predicate, page);
            return PageDataUtils.convertPageData(all, f -> {
                BaseUserListBean bean = new BaseUserListBean();
                bean.setId(f.getId());
                bean.setPhoneNumber(f.getTelephone());
                bean.setName(f.getRealName());
                bean.setCode(f.getCode());
                bean.setDepartId(f.getDepartId());
                BpEnterpriseInfo enterpriseInfo = infoMap.get(f.getWorkCompanyId());
                bean.setCompanyId(enterpriseInfo == null ? null : enterpriseInfo.getId());
                bean.setCompanyName(enterpriseInfo == null ? null : enterpriseInfo.getName());
                bean.setUserContractorFlag(0);
                if (f.getDepartId() != null) {
                    bean.setDepartName(departDao.findDepartNameById(f.getDepartId()));
                }
                bean.setJobId(f.getJob());
                if (f.getJob() != null) {
                    bean.setJobName(jobDao.findNameById(f.getJob()));
                }
                bean.setCertName(certificateService.findCertNameByUserIdAndType(f.getId(),
                        WorkCertificateTypes.TE_ZHONG_ZUO_YE.getCode()));
                bean.setGender(f.getGender());
                return bean;
            });
        } else {
            return bpContractorStaffService.userModelWfPage(condition.getNameOrCode(), condition.getCompanyId(), condition.getTenantId(), condition.getOrgCode(), page);
        }
    }

    @Override
    public List<BpUserBean> getUset(String name, Long typeId) {
        QBaseUser baseUser = QBaseUser.baseUser;
        Predicate predicate = baseUser.isNotNull();
        predicate = name == null ? predicate
                : ExpressionUtils.and(predicate, ExpressionUtils.or(baseUser.realName.like("%" + name + "%"),
                baseUser.role.like("%" + name + "%")));
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(baseUser.state.notIn(DataStateTypes.DELETE.getState()), baseUser.state.isNull()));
        predicate = typeId == null ? predicate : ExpressionUtils.and(predicate, baseUser.departId.eq(typeId));
        Iterable<BaseUser> all = dao.findAll(predicate);
        ArrayList<BpUserBean> list = new ArrayList<>();
        for (BaseUser user : all) {
            BpUserBean bpUserBean = new BpUserBean();
            bpUserBean.setRealName(user.getRealName());
            bpUserBean.setGender(user.getGender());
            bpUserBean.setDepartName(user.getDepartId());
            bpUserBean.setJobName(user.getJob());
            list.add(bpUserBean);
        }
        return list;
    }


    @Override
    public Long fife(BaseImageRepository baseImageRepository) {
        BaseImageRepository save = baseImageRespositoryDao.save(baseImageRepository);
        return save.getId();

    }

    @Override
    public List<BpJobBean> getJob() {
        List<BpJob> all = jobDao.findAll();
        ArrayList<BpJobBean> objects = new ArrayList<>();
        for (BpJob object : all) {
            BpJobBean bpJobBean = new BpJobBean();
            bpJobBean.setLabel(object.getName());
            bpJobBean.setValue(object.getId());
            objects.add(bpJobBean);
        }
        return objects;
    }

    @Override
    public List<BpWorkTypeBean> getWorkType() {
        List<BpWorkType> all = bpWorkTypeDao.findAll();
        ArrayList<BpWorkTypeBean> objects = new ArrayList<>();
        for (BpWorkType object : all) {
            BpWorkTypeBean bpJobBean = new BpWorkTypeBean();
            bpJobBean.setLabel(object.getName());
            bpJobBean.setValue(object.getId());
            objects.add(bpJobBean);
        }
        return objects;
    }

    @Override
    public List<BpDepartBean> getDepart() {
        List<BpDepart> all = departDao.findAll();
        ArrayList<BpDepartBean> objects = new ArrayList<>();
        for (BpDepart object : all) {
            BpDepartBean bpJobBean = new BpDepartBean();
            bpJobBean.setLabel(object.getName());
            bpJobBean.setValue(object.getId());
            objects.add(bpJobBean);
        }
        return objects;
    }

    @Override
    public void completeShiroUserInfo(Long userId, ShiroUser user) {
        BaseUser one = dao.getOne(userId);
        user.setTenentId(one.getTenentId());
        user.setDepartId(one.getDepartId());
        user.setRealName(one.getRealName());
        if (one.getDepartId() != null) {
            BpDepart depart = departDao.getOne(one.getDepartId());
            user.setDepartName(depart.getName());
            user.setDepartCode(depart.getCode());
            user.setDepartId(depart.getId()); // 设置部门Id
        }
        user.setJobId(one.getJob());
        if (one.getJob() != null) {
            BpJob job = jobDao.getOne(one.getJob());
            user.setJobName(job.getName());
        }
        // 获取公司信息
        Long companyId = one.getWorkCompanyId();
        if (companyId != null) {
            Optional<BpEnterpriseInfo> entInfo = bpEnterpriseInfoDao.findById(companyId);
            if (entInfo.isPresent()) {
                user.setCompanyId(companyId);
                user.setCompanyCode(entInfo.get().getOrgCode());
                user.setCompanyName(entInfo.get().getName());
            }
        }
        // 获取角色列表信息
        List<Long> roleIds = baseRoleUserLoginRoleDao.selectRoleIdsByUserId(one.getId());
        user.setRoleIds(roleIds);
        // 获取工号
        user.setCode(one.getCode());

        // departDao.getOne(userId)
    }

    @Override
    public List<BaseUserFindAllBean> getRole(Long role) {
        QBaseUser baseUser = QBaseUser.baseUser;
        Predicate predicate = baseUser.isNotNull();
        predicate = role == null ? predicate : ExpressionUtils.and(predicate, baseUser.role.eq(role));
        // 排除删除状态的人员： state=1 or state = null 的有效
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(baseUser.state.in(DataStateTypes.EFFECTIVE.getState()), baseUser.state.isNull()));
        Iterable<BaseUser> all = dao.findAll(predicate);
        ArrayList<BaseUserFindAllBean> list = new ArrayList<>();
        for (BaseUser u : all) {
            BaseUserFindAllBean b = new BaseUserFindAllBean();
            b.setDepartId(u.getDepartId());
            b.setName(u.getRealName());
            b.setId(u.getId());
            b.setTelePhone(u.getTelephone());
            if (u.getDepartId() != null) {
                // 部门
                departDao.findById(u.getDepartId()).ifPresent(one -> {
                    b.setDepartName(one.getName());
                    b.setRemark(one.getRemark());

                });

            }
            b.setJob(u.getJob());
            if (u.getJob() != null) {
                b.setJobName(jobDao.findNameById(u.getJob()));
            }
            b.setGender(u.getGender());
            b.setRole(u.getRole());
            if (u.getRole() == 0) {
                // 身份
                b.setRoleName("员工");
            }
            if (u.getRole() == 1) {
                // 身份
                b.setRoleName("管理人员");
            }
            if (u.getRole() == 2) {
                // 身份
                b.setRoleName("企业负责人");
            }
            // 显示顺序,兼容旧数据
            b.setShowNumber(u.getShowNumber());
            if (b.getShowNumber() == null) {
                b.setShowNumber(1);
            }
            list.add(b);
        }
        List<BaseUserFindAllBean> collect = list.stream().sorted(Comparator.comparing(BaseUserFindAllBean::getShowNumber, Comparator.nullsLast(Integer::compareTo))).collect(Collectors.toList());

        Collections.sort(list, new Comparator<BaseUserFindAllBean>() {
            @Override
            public int compare(BaseUserFindAllBean o1, BaseUserFindAllBean o2) {
                // 写法1：
                return o1.getShowNumber().compareTo(o2.getShowNumber());

            }
        });
        return list;
    }

    /**
     * 设置显示顺序
     *
     * @param list
     * @return
     */
    @Override
    public void setShowNumber(List<BaseUserFindAllBean> list) {
        for (BaseUserFindAllBean bean : list) {
            BaseUser user = dao.findById(bean.getId()).orElseThrow(() -> new IllegalArgumentException("人员不存在"));
            if ((bean.getShowNumber() + "").length() > 4) {
                throw new IllegalArgumentException("顺序数值不能超过4位");
            }
            user.setShowNumber(bean.getShowNumber());
            dao.save(user);
        }
    }

    @Override
    public Integer getAllUserTotalCount(String name, String departName, Integer type) {
        return dao.getAllUserTotalCount(name, departName, type);
    }

    @Override
    public List<Map<String, Object>> getAllUser(String name, String departName, Integer type, Integer page,
                                                Integer pageSize) {
        List<Map<String, Object>> resList = dao.getAllUser((page - 1) * pageSize, pageSize, name, departName, type);
        return resList;
    }

    @Override
    public BaseUser findByCode(String username, String companyCode) {
        QBaseUser baseUser = QBaseUser.baseUser;
        Predicate predicate = baseUser.isNotNull();
        predicate = username == null ? predicate : ExpressionUtils.and(predicate, baseUser.code.like(username));
        predicate = companyCode == null ? predicate
                : ExpressionUtils.and(predicate, baseUser.orgCode.like(companyCode));
        predicate = ExpressionUtils.and(predicate,
                ExpressionUtils.or(baseUser.state.notIn(DataStateTypes.DELETE.getState()), baseUser.state.isNull()));
        Iterable<BaseUser> all = dao.findAll(predicate);
        for (BaseUser user : all) {
            return user;
        }
        return null;
    }

    @Override
    public List<BaseUser> findAllNoLoginAccountUsers(String[] excludeUserCodes) {
        return (excludeUserCodes == null || excludeUserCodes.length == 0) ? dao.findNoLoginAccountUsers()
                : dao.findNoLoginAccountUsers(excludeUserCodes);
    }

    @Override
    public Page<BaseUserListBean> findDetailInfoWithExamScoreByPage(Pageable page, BaseUserListSearchBean condition,
                                                                    Long examId) {
        Page<BaseUserListBean> result = this.findDetailInfoByPage(page, condition);
        if (examId != null && result.getContent().size() > 0) {
            completeUserExamInfo(examId, result);
        }
        return result;
    }

    private void completeUserExamInfo(Long examId, Page<BaseUserListBean> result) {
        List<Long> userIds = result.getContent().stream().map(BaseUserListBean::getId).collect(Collectors.toList());
        List<EduExamRecord> ids = eduExamRecordDao.findByExamIdAndUserIdIn(examId, userIds);
        if (ids.isEmpty()) {
            return;
        }
        result.forEach(e -> {
            EduExamRecord record = findExamRecord(e.getId(), ids);
            if (record != null) {
                e.setExamId(examId);
                e.setPassScore(record.getPassScore());
                e.setScore(record.getScore());
            }
        });
    }

    private EduExamRecord findExamRecord(Long id, List<EduExamRecord> records) {
        for (EduExamRecord record : records) {
            if (record.getUserId().equals(id)) {
                return record;
            }
        }
        return null;
    }

    @Override
    public List<Long> queryUserIdsByNameContains(String userName) {
        return dao.getUserIdByNameContains(userName);
    }

    @Override
    public ResultBean getPwdBack(BaseUserPwdDto dto) {
        String email = dto.getEmail();
        BaseLoginAccount loginAccount = baseLoginAccountDao.findFirstByUserNameAndOrgCodeLike(dto.getUserName(),
                dto.getCompanyCode());
        if (loginAccount == null) {
            return ResultBean.fail(101, "不存在该用户");
        }
        BaseUser baseUser = loginAccount.getBaseUser();
        if (!email.equals(baseUser.getEmail())) {
            return ResultBean.fail(101, "该邮箱与绑定的用户名不一致，请重新填写");
        }
        int random = ThreadLocalRandom.current().nextInt(100000, 999999);
        String key = getKey(baseUser);
        redisClient.setEx(key, String.valueOf(random), 30, TimeUnit.MINUTES);
        try {
            mailService.setTextMail(new String[]{email}, "用户您好，您的密码找回验证码为" + random);
        } catch (Exception e) {
            log.warn("邮箱发送信息失败:", e.getMessage());
            redisClient.removeKey(key);
            return ResultBean.fail(101, "请确保邮箱服务器配置正确");
        }
        return ResultBean.wrapSuccessfulResult("已发送");
    }

    @Override
    public ResultBean auditPwd(BaseUserPwdDto dto) {
        String aduitPwd = dto.getAduitPwd();
        Assert.notNull(aduitPwd, "验证码不能为空");
        BaseLoginAccount loginAccount = baseLoginAccountDao.findFirstByUserNameAndOrgCodeLike(dto.getUserName(),
                dto.getCompanyCode());
        if (loginAccount == null) {
            return ResultBean.fail(101, "不存在该用户");
        }
        BaseUser baseUser = loginAccount.getBaseUser();
        String s = redisClient.get(getKey(baseUser));
        String auditKey = getAuditKey(baseUser);
        if (s == null) {
            redisClient.setEx(auditKey, "0", 2, TimeUnit.DAYS);
            return ResultBean.fail(101, "验证码已失效，请重试");
        }
        if (!aduitPwd.equals(s)) {
            redisClient.setEx(auditKey, "0", 2, TimeUnit.DAYS);
            return ResultBean.fail(101, "验证码错误");
        }
        redisClient.setEx(auditKey, "1", 2, TimeUnit.DAYS);
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public ResultBean editPwd(BaseUserPwdDto dto) {
        String newPassword = dto.getNewPassword();
        String comfirmPassword = dto.getComfirmPassword();
        BaseLoginAccount loginAccount = baseLoginAccountDao.findFirstByUserNameAndOrgCodeLike(dto.getUserName(),
                dto.getCompanyCode());
        if (loginAccount == null) {
            return ResultBean.fail(101, "不存在该用户");
        }
        BaseUser baseUser = loginAccount.getBaseUser();
        String auditKey = getAuditKey(baseUser);
        String s = redisClient.get(auditKey);
        if (s == null || "0".equals(s)) {
            return ResultBean.fail(101, "请先验证邮箱");
        }
        redisClient.removeKey(auditKey);
        Assert.isTrue(PasswordCheckUtil.check(newPassword), "密码格式不对，请重新填写");
        Assert.isTrue(newPassword.equals(comfirmPassword), "密码不一致，请重新输入");
        loginAccount.setPassword(newPassword);
        entryptPassword(loginAccount);
        baseLoginAccountDao.save(loginAccount);
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public ResultBean getIdByName(String name) {
        Assert.notNull(name, "name cannot be null");
        BaseUser baseUser = dao.findFirstByRealName(name);
        return ResultBean.success(baseUser.getId());
    }

    private void entryptPassword(BaseLoginAccount bean) {
        byte[] saltBytes = Digests.generateSalt(SALT_SIZE);
        String salt = Encodes.encodeHex(saltBytes);
        bean.setSalt(salt);
        String rawPass = bean.getPassword();
        String encPass = credentialsDigest.digest(rawPass, saltBytes);
        bean.setPassword(encPass);
    }

    // 邮件
    private String getKey(BaseUser baseUser) {
        return "password_mail:" + baseUser.getTenentId() + ":" + baseUser.getOrgCode() + ":" + baseUser.getId();
    }

    // 找回密码-重设密码 必须经过邮箱验证
    private String getAuditKey(BaseUser baseUser) {
        return "password_aduit:" + baseUser.getTenentId() + ":" + baseUser.getOrgCode() + ":" + baseUser.getId();
    }

    // 获取用户所在部门负责人信息
    @Override
    public BaseDepartDutyUserBean getDepartDutyUser(Long userId) {
        BaseDepartDutyUserBean userBean = null;
        BaseUser baseUser = dao.findById(userId).orElse(null);
        if (baseUser != null) {
            Long departId = baseUser.getDepartId();
            if (departId != null) {
                Optional<BpDepart> bpDepart = departDao.findById(departId);
                if (bpDepart.isPresent()) {
                    userBean = new BaseDepartDutyUserBean();
                    userBean.setDepartId(bpDepart.get().getId());
                    userBean.setDepartName(bpDepart.get().getName());
                    userBean.setId(bpDepart.get().getChiefId());
                    if (userBean.getId() != null) {
                        String chiefUserName = dao.getRealNameById(userBean.getId());
                        userBean.setRealName(chiefUserName);
                    }
                }
            }
        }
        return userBean;
    }

    // 获取用户所在部门负责人信息
    @Override
    public List<ApiUserDto> getDepartDutyUserList(Long departId, Integer level) {
        List<BaseDepartDutyUserBean> userBeans = new ArrayList<>();
        List<ApiUserDto> apiUserDtoList = new ArrayList<>();
        if (departId != null) {
            Optional<BpDepart> bpDepart = departDao.findById(departId);
            if (bpDepart.isPresent()) {
                setUserBean(bpDepart.get(), userBeans);
                //向上追溯level
                if (level > 0) {
                    for (int i = 1; i <= level; i++) {
                        departId = departDao.findParentIdById(departId);
                        Optional<BpDepart> bpDepartP = departDao.findById(departId);
                        bpDepartP.ifPresent(depart -> setUserBean(depart, userBeans));
                    }
                }
            }
        }
        if (!CollectionUtils.isEmpty(userBeans)) {
            userBeans.forEach(bean -> {
                ApiUserDto apiUserDto = new ApiUserDto();
                apiUserDto.setId(bean.getId());
                apiUserDto.setName(bean.getRealName());
                apiUserDtoList.add(apiUserDto);
            });
        }
        log.info("======findDepartLeaderByDepartId=====" + JSON.toJSONString(apiUserDtoList));
        return apiUserDtoList;
    }

    private void setUserBean(BpDepart bpDepart, List<BaseDepartDutyUserBean> userBeans) {
        BaseDepartDutyUserBean userBean = new BaseDepartDutyUserBean();
        userBean.setDepartId(bpDepart.getId());
        userBean.setDepartName(bpDepart.getName());
        userBean.setId(bpDepart.getChiefId());
        if (userBean.getId() != null) {
            String chiefUserName = dao.getRealNameById(userBean.getId());
            userBean.setRealName(chiefUserName);
        }
        userBeans.add(userBean);
    }

    /**
     * 获取人员下拉列表
     *
     * @return
     */
    @Override
    public List<SimpleSelectListBean> getUserSimpleList() {
        List<SimpleSelectListBean> data = new ArrayList<>();
        List<BaseUser> list = dao.getUserList();
        for (BaseUser b : list) {
            SimpleSelectListBean bean = new SimpleSelectListBean();
            bean.setValue(b.getId());
            bean.setLabel(b.getRealName());
            data.add(bean);
        }
        return data;
    }

    // flag 1 同步所有人员; 0 同步部分人员
    @Override
    public ResultBean locateSyncUser(Integer flag, List<Long> userIds) {
        List<BaseUser> baseUserList;
        if (flag == 1) {
            baseUserList = dao.finAllUser();
        } else {
            baseUserList = dao.findAllById(userIds);
        }
        locateServerService.syncLocateUsers(baseUserList, 0);
        return ResultBean.defaultSuccessResult();
    }

    /**
     * 卡口信息
     *
     * @param page
     * @param condition
     * @return
     */
    @Override
    public Page<BaseCreditCardRecordBean> getCreditCardRecord(Pageable page, BaseCreditCardRecordSearchBean condition) {
        page = PageDataUtils.addOrderByDesc(page, "id");
        Predicate predicate = prepareCreditCardRecord(condition);
        Page<BaseCreditCardRecord> data = predicate == null ? baseCreditCardRecordDao.findAll(page)
                : baseCreditCardRecordDao.findAll(predicate, page);
        return PageDataUtils.convertPageData(data,
                new PageDataConvert<BaseCreditCardRecordBean, BaseCreditCardRecord>() {
                    @Override
                    public BaseCreditCardRecordBean convert(BaseCreditCardRecord record) {
                        BaseCreditCardRecordBean bean = new BaseCreditCardRecordBean();
                        BeanUtils.copyProperties(record, bean);
                        // if (record.getUserTypeId() != null) {
                        // bean.setUserTypeName(baseTypeGroupItemDao.getNameById(record.getUserTypeId()));
                        // }
                        if (record.getTypeFlag() == null || record.getTypeFlag() == 0) {
                            bean.setTypeFlagName("卡口信息");
                        } else if (record.getTypeFlag() == 1) {
                            bean.setTypeFlagName("车辆出入信息");
                        }
                        bean.setUserTypeName(record.getUserTypeName());
                        return bean;
                    }
                });
    }

    /**
     * 卡口人员信息详情
     *
     * @param typeFlag 1：访客，2：承揽商，3：公司员工
     * @param code
     * @return
     */
    @Override
    public ResultBean getCreditCardUserDetail(Integer typeFlag, String code) {
        if (typeFlag == null) {
            return null;
        } else if (typeFlag.intValue() == 1) {
            return ResultBean.success(1);
        } else if (typeFlag.intValue() == 2) {
            BpContractorStaff staff = bpContractorStaffDao.findByCode(code);
            if (staff != null) {
                return bpContractorStaffService.get(staff.getId());
            } else {
                return null;
            }
        } else if (typeFlag.intValue() == 3) {
            BaseUser user = dao.findByCode(code);
            if (user != null) {
                return ResultBean.success(this.findById(user.getId()));
            } else {
                return null;
            }
        } else {
            return null;
        }

    }

    private static final List<UserDataSourceDto> dataSourceDtoList = new ArrayList<>(23);

    static {
        dataSourceDtoList.add(new UserDataSourceDto("realName", "姓名"));
        dataSourceDtoList.add(new UserDataSourceDto("gender", "性别"));
        dataSourceDtoList.add(new UserDataSourceDto("departName", "部门"));
        dataSourceDtoList.add(new UserDataSourceDto("jobName", "岗位"));
        dataSourceDtoList.add(new UserDataSourceDto("telephone", "联系电话"));
        dataSourceDtoList.add(new UserDataSourceDto("email", "邮箱"));
        dataSourceDtoList.add(new UserDataSourceDto("education", "学历"));
        dataSourceDtoList.add(new UserDataSourceDto("major", "专业"));
        dataSourceDtoList.add(new UserDataSourceDto("healthStatus", "健康状况"));
        dataSourceDtoList.add(new UserDataSourceDto("code", "工号"));
        dataSourceDtoList.add(new UserDataSourceDto("role", "身份"));
        dataSourceDtoList.add(new UserDataSourceDto("workCompanyName", "工作单位"));
        dataSourceDtoList.add(new UserDataSourceDto("sn", "定位卡号"));
        dataSourceDtoList.add(new UserDataSourceDto("idCardType", "证件类型"));
        dataSourceDtoList.add(new UserDataSourceDto("work", "从业所在地"));
        dataSourceDtoList.add(new UserDataSourceDto("title", "职称/技能等级"));
        dataSourceDtoList.add(new UserDataSourceDto("workTypeName", "工种"));
        dataSourceDtoList.add(new UserDataSourceDto("cardNumber", "门禁卡号"));
        dataSourceDtoList.add(new UserDataSourceDto("nation", "民族"));
        dataSourceDtoList.add(new UserDataSourceDto("idCardNo", "证件号码"));
        dataSourceDtoList.add(new UserDataSourceDto("census", "户籍所在地"));
        dataSourceDtoList.add(new UserDataSourceDto("address", "通讯地址"));
        dataSourceDtoList.add(new UserDataSourceDto("joinWorkDate", "参加工作时间"));
    }

    @Override
    public ResultBean getAllFields(Pageable pageable) {
        List<UserDataSourceDto> list = PageableUtil.getList(pageable, dataSourceDtoList);
        PageDataUtils.addOrderByDesc(pageable, "id");
        PageImpl<UserDataSourceDto> page = new PageImpl<>(list, pageable, dataSourceDtoList.size());
        return ResultBean.pageData(page);
    }

    /**
     * 添加人员报警模板
     *
     * @param userId
     * @param templateId
     * @return
     */
    @Override
    public BaseUser editAlarmTemplate(Long userId, Long templateId, String templateName) {
        BaseUser user = dao.findById(userId).orElseThrow(() -> new IllegalArgumentException("人员不存在"));
        if (templateId != null && 0 != templateId) {
            user.setAlarmTemplateId(templateId);
            user.setAlarmTemplateName(templateName);
        } else {
            user.setAlarmTemplateId(null);
            user.setAlarmTemplateName(null);
        }
        BaseUser save = dao.save(user);
        locateServerService.syncLocateUsers(Lists.newArrayList(save), 0);
        return save;
    }

    @Override
    public ResultBean getIdBySn(String sn) {
        BaseUser user = dao.findFirstBySn(sn);
        return ResultBean.success(user == null ? null : user.getId());
    }

    @Override
    public BaseUserCardNumBean findUserInfoByCardNumber(List<Long> certIds, String cardNumber,
                                                        boolean userContractorFlag) {

        BaseUserCardNumBean userCardNumBean = null;
        if (userContractorFlag) {
            BpContractorStaff contractorStaff = bpContractorStaffDao.findFirstByCardNumberAndState(cardNumber, 1);
            if (contractorStaff != null) {
                userCardNumBean = BaseUserCardNumBean.builder().userId(contractorStaff.getId())
                        .realName(contractorStaff.getName()).build();
            }
        } else {
            BaseUser baseUser = dao.findFirstByCardNumber(cardNumber);
            if (baseUser != null) {
                if (!CollectionUtils.isEmpty(certIds)) {
                    List<EduCertificateUser> certs = eduCertificateUserDao
                            .getEffectiveCertByUserIdAndCertIds(baseUser.getId(), certIds);
                    if (certIds.size() == certs.size()) {
                        userCardNumBean = BaseUserCardNumBean.builder().userId(baseUser.getId())
                                .realName(baseUser.getRealName()).build();
                    }
                } else {
                    userCardNumBean = BaseUserCardNumBean.builder().userId(baseUser.getId())
                            .realName(baseUser.getRealName()).build();
                }
            }
        }
        return userCardNumBean;
    }

    // 卡口分页条件
    private Predicate prepareCreditCardRecord(BaseCreditCardRecordSearchBean condition) {
        QBaseCreditCardRecord record = QBaseCreditCardRecord.baseCreditCardRecord;
        Predicate p = null;

        // 0卡口,1车辆
        if (condition.getTypeFlag() != null) {
            p = ExpressionUtils.and(p, record.typeFlag.eq(condition.getTypeFlag()));
        }

        // 刷卡时间
        if (condition.getStartTime() != null && condition.getEndTime() != null) {
            LocalDateTime startTime = LocalDateTime.of(DateTimeUtil.date2LocalDate(condition.getStartTime()),
                    LocalTime.of(0, 0, 0));
            LocalDateTime endTime = LocalDateTime.of(DateTimeUtil.date2LocalDate(condition.getEndTime()),
                    LocalTime.of(23, 59, 59));
            p = ExpressionUtils.and(p, record.slotCardTime.between(DateTimeUtil.localDateTime2Date(startTime),
                    DateTimeUtil.localDateTime2Date(endTime)));
        }

        // 人员类型
        if (condition.getUserTypeId() != null) {
            p = ExpressionUtils.and(p, record.userTypeId.eq(condition.getUserTypeId()));
        }

        // 姓名
        if (condition.getUserName() != null) {
            p = ExpressionUtils.and(p, record.userName.contains(condition.getUserName()));
        }

        // 所属公司/承揽商
        if (condition.getCompanyName() != null) {
            p = ExpressionUtils.and(p, record.companyName.contains(condition.getCompanyName()));
        }
        // 职号/证件号码
        if (condition.getIdNumber() != null) {
            p = ExpressionUtils.and(p, record.idNumber.contains(condition.getIdNumber()));
        }
        // 卡号
        if (condition.getCardCode() != null) {
            p = ExpressionUtils.and(p, record.cardCode.contains(condition.getCardCode()));
        }
        // 刷卡成功
        if (condition.getCreditCardTag() != null) {
            p = ExpressionUtils.and(p, record.creditCardTag.eq(condition.getCreditCardTag()));
        }
        return p;
    }

    private List<Long> getUserTypeItemList() {
        List<Long> typeItemList = new ArrayList<>();
        BaseTypeGroup typeGroup = typeGroupDao.findByName("人员类型");
        List<BaseTypeGroupItem> list = baseTypeGroupItemDao.findByTypeGroupId(typeGroup.getId());
        if (list != null) {
            for (BaseTypeGroupItem d : list) {
                typeItemList.add(d.getId());
            }
        }
        return typeItemList;
    }

    @Override
    public BatchUploadResult batchUploadIdImages(MultipartFile file, String type) {
        BatchUploadResult result = new BatchUploadResult();
        List<BaseUserBean> updateUsers = new ArrayList<>();
        List<BatchUploadInfoBean> list = unzipAndParseUploadInfo(file, "UTF-8", "GBK");
        list.forEach(f -> {
            if (f.isIgnored()) {
                result.getIgnoreItems().add(f.getFilename());
            }
        });
        List<BatchUploadInfoBean> infos = list.stream().filter(f -> !f.isIgnored()).collect(Collectors.toList());
        if (infos.size() > 0) {
            boolean sync = baseConfigService.checkIfSync();
            List<String> certNos = infos.stream().map(BatchUploadInfoBean::getBaseName)
                    .collect(Collectors.toList());
            List<BaseUser> users = findUserByType(certNos, type);
            UUID uuid = UUID.randomUUID();
            File newDir = new File(infos.get(0).getDirPath(), uuid.toString());
            newDir.mkdir();
            infos.forEach(e -> {
                Optional<BaseUser> first = users.stream().filter(u -> userMatches(u, e.getBaseName(), type))
                        .findFirst();
                if (first.isPresent()) {
                    if (sync) {
                        try {
                            zipProcessService.copyFile(e.getFile(), new File(newDir.getAbsolutePath(), first.get().getUniqueId() + "." + e.getSuffix()));
                        } catch (Exception ex) {
                            log.error(ex.getMessage(), ex);
                        }
                    }
                    first.get().setIdCardImgId(e.getId());
                    dao.save(first.get());
                    BaseUserBean baseUserBean = new BaseUserBean();
                    baseUserBean.setUserId(first.get().getId());
                    baseUserBean.setPath(imageUploadDir + File.separator + e.getPath());
                    baseUserBean.setIdCardImgId(first.get().getIdCardImgId());
                    updateUsers.add(baseUserBean);
                    result.setSucceedCount(result.getSucceedCount() + 1);
                } else {
                    result.setFailCount(result.getFailCount() + 1);
                    result.getFailItems().add(e.getFilename());
                }
            });
            //同步
            if (sync) {
                try {
                    ZipUtil.toZip(newDir, new FileOutputStream(newDir.getAbsolutePath() + File.separator + uuid.toString() + ".zip"), true);
                } catch (FileNotFoundException e) {
                    log.error(e.getMessage(), e);
                }
                this.syncUserHeanImage(newDir.getAbsolutePath() + File.separator + uuid.toString() + ".zip");
            }
            // 清理临时目录
            zipProcessService.deleteTempDir(infos.get(0).getTempDir());
            //同步百度人脸照片
            log.info("updateUsers++----------------->" + JSON.toJSONString(updateUsers));
            if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(updateUsers)) {
                baseUserFaceLogService.updateFace(updateUsers);
            }
        }
        return result;
    }

    private void syncUserHeanImage(String path) {
        baseImageSyncService.batchPeopleHeadImages(path, locateServerService.getBuildId(), locateServerService.getLoginToken(), "user");
    }

    private List<BatchUploadInfoBean> unzipAndParseUploadInfo(MultipartFile file, String... tryEncodings) {
        for (String encoding : tryEncodings) {
            try {
                List<BatchUploadInfoBean> infos = zipProcessService.batchUploadImages(file.getInputStream(), true, 1,
                        Charset.forName(encoding), "jpg", "jpeg", "png");
                return infos;
            } catch (Exception e) {
                log.error("解析{}出错，encoding={}", file.getOriginalFilename(), encoding, e);
            }
        }
        throw new RuntimeException("解析zip文件异常:file=" + file.getOriginalFilename());
    }

    private List<BaseUser> findUserByType(List<String> certNos, String type) {
        Predicate p = null;
        if ("sn".equals(type)) {
            p = QBaseUser.baseUser.sn.in(certNos);
        } else if ("name".equals(type)) {
            p = QBaseUser.baseUser.realName.in(certNos);
        } else if ("code".equals(type)) {
            p = QBaseUser.baseUser.code.in(certNos);
        }
        p = ExpressionUtils.and(p, QBaseUser.baseUser.state.ne(DataStateTypes.DELETE.getState()).or(
                QBaseUser.baseUser.state.isNull()
        ));
        return p == null ? Collections.EMPTY_LIST : (List) dao.findAll(p);
    }

    private boolean userMatches(BaseUser u, String baseName, String type) {
        if ("sn".equals(type)) {
            return baseName.equals(u.getSn());
        }
        if ("name".equals(type)) {
            return baseName.equals(u.getRealName());
        }
        if ("code".equals(type)) {
            return baseName.equals(u.getCode());
        }
        return false;
    }

    //
    // private Long getUserTypeItemId(String name) {
    // BaseTypeGroup typeGroup = typeGroupDao.findByName("人员类型");
    // List<BaseTypeGroupItem> list = baseTypeGroupItemDao.findByTypeGroupIdAndName(typeGroup.getId(),name);
    // if (list != null) {
    // for (BaseTypeGroupItem d : list) {
    // typeItemList.add(d.getId());
    // }
    // }
    // return typeItemList;
    // }


    @Override
    public List<EduCertUserDto> getUserOrContractorUserList(EduCertUserQueryBean bean) {
        Integer userContractorFlag = bean.getUserContractorFlag();
        userContractorFlag = userContractorFlag == null ? 0 : userContractorFlag;
        if (userContractorFlag == 0) {
            return getEduUserCert(bean);
        } else {
            return getEduContractorUserCert(bean);
        }
    }

    /**
     * 获取人员的列表
     *
     * @param bean
     * @return
     */
    private List<EduCertUserDto> getEduUserCert(EduCertUserQueryBean bean) {
        return baseUserMapper.findUserList(bean.getName(), bean.getEnterPrise(), bean.getDepartId(), Context.getCurrentTenantId(), Context.getCompanyCode());
    }

    /**
     * 获取承包商人员的列表
     *
     * @param bean
     * @return
     */
    private List<EduCertUserDto> getEduContractorUserCert(EduCertUserQueryBean bean) {
        return baseUserMapper.findContractUser(bean.getName(), bean.getEnterPrise(), Context.getCurrentTenantId(), Context.getCompanyCode());
    }

    /**
     * 根据岗位id获取岗位下的所有人员信息
     *
     * @return
     */
    @Override
    public List<BaseJobAndUserBean> findUserByJobIds(List<Long> jobIds) {
        List<BaseJobAndUserBean> baseJobAndUserBeanList = new ArrayList<>();
        for (Long jobId : jobIds) {
            List<SimpleUserBean> baseUserJobBeanList = baseUserMapper.findUserByJobId(jobId);
            String jobName = jobDao.getNameById(jobId);
            BaseJobAndUserBean baseJobAndUserBean = new BaseJobAndUserBean();
            baseJobAndUserBean.setJobId(jobId);
            baseJobAndUserBean.setJobName(jobName);
            baseJobAndUserBean.setBaseUserJobBeanList(baseUserJobBeanList);
            baseJobAndUserBeanList.add(baseJobAndUserBean);
        }
        return baseJobAndUserBeanList;
    }

    @Override
    public List<Long> findUserIdsByTargetIds(String orgType, List<Long> jobIds) {
        List<Long> list = new ArrayList<>();
        if ("J".equals(orgType)) {
            list = baseUserMapper.findUserIdsByJobTargetIds(jobIds);
        } else if ("D".equals(orgType)) {
            list = baseUserMapper.findUserIdsByDepartTargetIds(jobIds);
        }
        return list;
    }

    @Override
    public int getUserOrContractorUserCount(EduCertUserQueryBean bean) {
        Integer userContractorFlag = bean.getUserContractorFlag();
        userContractorFlag = userContractorFlag == null ? 0 : userContractorFlag;
        if (userContractorFlag == 0) {
            return baseUserMapper.selectuserCount(bean.getName(), bean.getEnterPrise(), bean.getDepartId(), Context.getCurrentTenantId(), Context.getCurrentOrgCode());
        } else {
            return baseUserMapper.selectContractorCount(bean.getName(), bean.getEnterPrise(), Context.getCurrentTenantId(), Context.getCurrentOrgCode());
        }

    }

    @Override
    public List<ApiUserDto> findUserList(String departIds, String jobIds, String roleIds, String userIds, Long tenantId, String orgCode) {
        //为兼容后期可能会有多个部门，岗位，角色搜索。多个时前端使用  ,  分割
        List<Long> departIdList = null;
        List<Long> jobIdList = null;
        List<Long> roleIdList = null;
        List<Long> userIdList = null;
        Set<Long> allDepartIds = new HashSet<>();
        if (StringUtils.isNotBlank(departIds)) {
            departIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(departIds).stream().map(Long::new).collect(Collectors.toList());
            //同时拿到每个部门下的子部门id,最终去重成为list
            if (CollectionUtil.isNotEmpty(departIdList)) {
                Set<Long> departIdSet = new HashSet<>(departIdList);
                /*for (Long departId : departIdSet) {
                    List<Long> departments = departments(departId);
                    allDepartIds.addAll(departments);
                }*/
                allDepartIds.addAll(departIdSet);
            }
        }
        if (StringUtils.isNotBlank(jobIds)) {
            jobIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(jobIds).stream().map(Long::new).collect(Collectors.toList());
        }
        if (StringUtils.isNotBlank(roleIds)) {
            roleIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(roleIds).stream().map(Long::new).collect(Collectors.toList());
        }
        if (StringUtils.isNotBlank(userIds)) {
            userIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(userIds).stream().map(Long::new).collect(Collectors.toList());
        }
        List<ApiUserDto> userListForApi = baseUserMapper.findUserListForApi(allDepartIds, jobIdList, roleIdList, userIdList, tenantId, orgCode);
        convertForUser(userListForApi);
        return userListForApi;
    }

    public List<Long> departments(Long id) {
        List<Long> ids = new ArrayList<>();
        ids.add(id);
        ids.addAll(this.findChild(id));
        return ids;
    }


    /**
     * 查询子部门
     *
     * @param id
     * @return
     */
    private List<Long> findChild(Long id) {
        List<Long> ids = new ArrayList<>();
        Pageable of = PageRequest.of(0, Integer.MAX_VALUE);
        List<BpDepartListBean> contents = departService.get(id, of).getContent();
        contents.forEach(c -> {
            ids.add(c.getId());
        });
        return ids;
    }

    /**
     * 找出岗位,部门,角色赋值给前端
     *
     * @param userListForApi
     */
    private void convertForUser(List<ApiUserDto> userListForApi) {
        for (ApiUserDto apiUserDto : userListForApi) {
            List<BaseRole> roleList = baseRoleDao.findByUserId(apiUserDto.getId());
            List<ApiUserRoleDto> apiUserRoleDtos = new ArrayList<>();
            for (BaseRole baseRole : roleList) {
                ApiUserRoleDto apiUserRoleDto = new ApiUserRoleDto();
                apiUserRoleDto.setRoleId(baseRole.getId());
                apiUserRoleDto.setRoleName(baseRole.getName());
                apiUserRoleDtos.add(apiUserRoleDto);
            }
            apiUserDto.setRole(apiUserRoleDtos);

            List<ApiUserJobDto> job = new ArrayList<>();
            ApiUserJobDto userJobDto = new ApiUserJobDto();
            userJobDto.setJobId(apiUserDto.getJobId());
            userJobDto.setJobName(apiUserDto.getJobName());
            job.add(userJobDto);
            apiUserDto.setJob(job);

            List<ApiUserDepartDto> depart = new ArrayList<>();
            ApiUserDepartDto departDto = new ApiUserDepartDto();
            departDto.setDepartId(apiUserDto.getDepartId());
            departDto.setDepartName(apiUserDto.getDepartName());
            depart.add(departDto);
            apiUserDto.setDepart(depart);
        }
    }

    @Override
    public ResultBean findUserListByPage(Integer page, Integer size, String departIds, String jobIds, String roleIds, String userIds, String userName, String departName, String code, Long tenantId, String orgCode) {
        //为兼容后期可能会有多个部门，岗位，角色搜索。多个时前端使用  ,  分割
        List<Long> departIdList = null;
        List<Long> jobIdList = null;
        List<Long> roleIdList = null;
        List<Long> userIdList = null;
        if (StringUtils.isNotBlank(departIds)) {
            departIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(departIds).stream().map(Long::new).collect(Collectors.toList());
        }
        if (StringUtils.isNotBlank(jobIds)) {
            jobIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(jobIds).stream().map(Long::new).collect(Collectors.toList());
        }
        if (StringUtils.isNotBlank(roleIds)) {
            roleIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(roleIds).stream().map(Long::new).collect(Collectors.toList());
        }
        if (StringUtils.isNotBlank(userIds)) {
            userIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(userIds).stream().map(Long::new).collect(Collectors.toList());
        }
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<ApiUserDto> apiUserVoPage = new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(page + 1, size);
        com.baomidou.mybatisplus.extension.plugins.pagination.Page<ApiUserDto> userListByPageForApi = baseUserMapper.findUserListByPageForApi(apiUserVoPage, departIdList, jobIdList, roleIdList, userIdList, userName, departName, code, tenantId, orgCode);
        if (CollectionUtil.isNotEmpty(userListByPageForApi.getRecords())) {
            convertForUser(userListByPageForApi.getRecords());
            return ResultBean.pageData(userListByPageForApi.getRecords(), userListByPageForApi.getTotal());
        }
        return ResultBean.pageData(new ArrayList<>(), userListByPageForApi.getTotal());
    }

    @Override
    public List<BpDepartBean> getNewDepart(Long jobId) {
        List<BpDepart> all = new ArrayList<>();
        if (jobId == null) {
            all = departDao.findAll();
        } else {
            List<Long> deptIds = baseUserMapper.findDepartByJobId(jobId);
            if (!CollectionUtils.isEmpty(deptIds)) {
                all = departDao.findByIds(deptIds);
            }
        }
        ArrayList<BpDepartBean> objects = new ArrayList<>();
        for (BpDepart object : all) {
            BpDepartBean bpJobBean = new BpDepartBean();
            bpJobBean.setLabel(object.getName());
            bpJobBean.setValue(object.getId());
            objects.add(bpJobBean);
        }
        return objects;
    }

    @Override
    public List<BpJobBean> getNewJob(Long departId) {
        List<BpJob> all = new ArrayList<>();
        if (departId == null) {
            all = jobDao.findAll();
        } else {
            List<Long> jobIds = baseUserMapper.findJobByDepartId(departId);
            if (!CollectionUtils.isEmpty(jobIds)) {
                all = jobDao.findbyIds(jobIds);
            }
        }
        ArrayList<BpJobBean> objects = new ArrayList<>();
        for (BpJob object : all) {
            BpJobBean bpJobBean = new BpJobBean();
            bpJobBean.setLabel(object.getName());
            bpJobBean.setValue(object.getId());
            objects.add(bpJobBean);
        }
        return objects;
    }

    @Override
    public boolean needAutograph(Long currentUserId) {
        boolean needAutograph = false;
        BaseConfig config = baseConfigService.getBaseConfigFromRedis(BaseConfigCodes.AUTOGRAPH);
        if (config != null && StringUtils.isNotBlank(config.getValue())) {
            if (config.getValue().equals("开启")) {
                BaseUser baseUser = dao.findById(currentUserId).orElse(null);
                if (baseUser != null && StringUtils.isBlank(baseUser.getAutograph()) || StringUtils.isBlank(baseUser.getFlowSignature())) {
                    needAutograph = true;
                }
            }
        }

        return needAutograph;
    }

    @Override
    public void updateAutograph(String autograph, String flowSignature, Long currentUserId) {
        Optional<BaseUser> byId = dao.findById(currentUserId);
        if (byId.isPresent() && StringUtils.isNotBlank(autograph)) {
            BaseUser baseUser = byId.get();
            baseUser.setAutograph(autograph);
            baseUser.setFlowSignature(flowSignature);
            dao.save(baseUser);
        }
    }

    @Override
    public Long selectUserIdByName(String userName) {
        return baseUserMapper.selectUserIdByName(userName);
    }

    @Override
    public Long countNumByName(String userName) {
        return baseUserMapper.countNumByName(userName);
    }

    @Override
    public ResultBean syncFace(List<Long> ids) {
        if (CollectionUtils.isEmpty(ids)) {
            return ResultBean.defaultSuccessResult();
        }
        BaseConfig syncConfig = baseConfigService.findFirstConfig(BaseConfigCodes.BAIDU_FACE_ID_APP_SYNC);
        if (syncConfig == null || StringUtils.isBlank(syncConfig.getValue()) || syncConfig.getValue().equals("关闭")) {
            HashMap<Object, Object> map = new HashMap<>();
            map.put("code", 220);
            map.put("msg", "当前系统暂未启用人脸识别功能或人脸识别配置异常，请前往配置管理中配置人脸识别参数!");
            return ResultBean.success(map);
        }
        if (StringUtils.isBlank(BaiduSample.APP_ID) || StringUtils.isBlank(BaiduSample.API_KEY) || StringUtils.isBlank(BaiduSample.SECRET_KEY)) {
            HashMap<Object, Object> map = new HashMap<>();
            map.put("code", 220);
            map.put("msg", "当前系统暂未启用人脸识别功能或人脸识别配置异常，请前往配置管理中配置人脸识别参数!");
            return ResultBean.success(map);
        }
        List<BaseUser> userList = dao.getAllByIdsAndShowState(ids);
        List<BaseUserBean> baseUserBeans = new ArrayList<>();
        List<Long> userIds = userList.stream().filter(e -> e.getIdCardImgId() != null).map(BaseUser::getIdCardImgId).collect(Collectors.toList());
        Map<Long, String> idCardMap = baseImageRepositoryService.findByIds(userIds);
        for (BaseUser baseUser : userList) {
            BaseUserBean bean = new BaseUserBean();
            if (baseUser.getIdCardImgId() != null) {
                bean.setIdCardImgId(baseUser.getIdCardImgId());
                bean.setPath(idCardMap.get(baseUser.getIdCardImgId()));
            }
            bean.setUserId(baseUser.getId());
            baseUserBeans.add(bean);
        }
        baseUserFaceLogService.updateFace(baseUserBeans);

        return ResultBean.defaultSuccessResult();
    }

    @Override
    public List<BaseUser> getAllByIdsAndShowState(List<Long> ids) {
        return dao.getAllByIdsAndShowState(ids);
    }
/*
    @Override
    public  void updateFace(List<BaseUser> userList){
        List<BaseUserFaceLog> logs=new ArrayList<>();
        String groupId =  getGroupId();
        for (BaseUser user : userList) {
            BaseUserFaceLog log = new BaseUserFaceLog();
            try {
                log.setSyncTime(new Date());
                log.setUserId(user.getId());
                if (user.getIdCardImgId()==null) {
                    log.setErrMsg("人脸照片不存在");
                    logs.add(log);
                    continue;
                }
                String path = baseImageRepositoryService.findAbsolutePathById(user.getIdCardImgId());
                if (StringUtils.isBlank(path)) {
                    log.setErrMsg("人脸照片不存在");
                    logs.add(log);
                    continue;
                }
                String imageBase64 = DzPrtqUtils.readFileToBase64(new FileInputStream(path));
//                String orgCode=user.getOrgCode().replaceAll("-","_");
//                String groupId=user.getTenentId()+"_"+orgCode
                JSONObject jsonObject = new BaiduFace().addUser(BaiduSample.client, imageBase64, "BASE64", groupId, user.getId().toString(), null);
                String errorCode = jsonObject.get("error_code").toString();
                if (errorCode.equals("0")) {
                    JSONObject result = jsonObject.getJSONObject("result");
                    String faceToken = result.getString("face_token");
                    user.setFaceToken(faceToken);
                    baseUserMapper.updateById(user);
                    log.setErrMsg("成功");
                }else {
                    BaiduCodeEnum baiduCodeEnum = BaiduCodeEnum.find(errorCode);
                    log.setErrMsg(baiduCodeEnum==null?"":baiduCodeEnum.getErrMsg());
                }
                log.setErrCode(errorCode);
                log.setDetail(jsonObject.toString());
                logs.add(log);
                //线程休眠1秒
                Thread.sleep(1000);
            } catch (IOException e) {
                e.printStackTrace();
            }catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        baseUserFaceLogService.saveBatch(logs);
    }*/

    @Override
    public List<ApiUserBeanDto> findBeanList(String userIdStr, String userNameStr, Long tenantId, String orgCode) {
        //为兼容后期可能会有多个部门，岗位，角色搜索。多个时前端使用  ,  分割

        if (!StringUtils.isAnyBlank(userIdStr, userNameStr)) {
            List<Long> userIdList = Splitter.on(Constant.SPLIT_COMMA).trimResults().splitToList(userIdStr).stream().map(Long::new).collect(Collectors.toList());
            List<String> userNameList = Arrays.asList(StrUtil.split(userNameStr, Constant.SPLIT_COMMA));
            List<ApiUserBeanDto> userList = baseUserMapper.findUserBeanListForApi(userIdList, userNameList, tenantId, orgCode);
            List<ApiUserBeanDto> contractorList = contractorStaffMapper.findContractorListForApi(userIdList, userNameList, tenantId, orgCode);
            userList.addAll(contractorList);
            return userList;
        }
        return Collections.emptyList();

    }

    public String getGroupId() {
        String groupId = "";
        BaseConfig groupIdConfig = baseConfigService.findFirstConfig(BaseConfigCodes.LOCATE_CURRENT_BUILD_ID);
        if (groupIdConfig != null && StringUtils.isNotBlank(groupIdConfig.getValue())) {
            groupId = groupIdConfig.getValue();
        }
        return groupId;
    }


    @Override
    public List<BaseUserDepartBean> findUserByDepart(BaseUserDepartJobBean bean) {
        if (bean.getJobIds().isEmpty() && bean.getDepartIds().isEmpty() && bean.getUserIds().isEmpty()) {
            return null;
        }
        return baseUserMapper.findUserByDepart(bean.getJobIds(), bean.getDepartIds(), bean.getUserIds());
    }
}
